package com.hoo.permission.sdk.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hoo.permission.sdk.server.dao.ISysResourceDao;
import com.hoo.permission.sdk.server.dao.ISysRoleResourceDao;
import com.hoo.permission.sdk.server.dao.ISysUserResourceDao;
import com.hoo.permission.sdk.server.domain.entity.SysResource;
import com.hoo.permission.sdk.server.domain.model.ResourceType;
import com.hoo.permission.sdk.server.service.ISysResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.*;

/**
 * 系统资源服务层实现类
 *
 * @author hank
 * @create 2020-06-28 下午11:14
 **/
@Service
public class SysResourceServiceImpl implements ISysResourceService {

    @Autowired ISysResourceDao resourceDao;
    @Autowired ISysRoleResourceDao roleResourceDao;
    @Autowired ISysUserResourceDao userResourceDao;


    @Override
    public boolean add(SysResource entity) {
        this.validate(entity);
        return resourceDao.add(entity);
    }

    @Override
    public boolean update(SysResource entity) {
        this.validate(entity);
        return entity.getId() == null ? resourceDao.add(entity) : resourceDao.update(entity);
    }

    private void validate(SysResource entity) {
        if(entity.getType() == ResourceType.URL) {
            // 如果待插入数据type = 1(菜单), 这里校验 parentId 的 type 也必须为 1
            if(entity.getParentId() != null && entity.getParentId() != 0L) {
                SysResource parentResource = resourceDao.get(entity.getParentId());
                if(parentResource.getType() != ResourceType.URL) {
                    throw new IllegalArgumentException("归属菜单不合法");
                }
            }
            // url 和 组件地址 不可空
            if(StringUtils.isEmpty(entity.getUrl())) {
                throw new IllegalArgumentException("菜单URL不合法");
            }
            if(StringUtils.isEmpty(entity.getPath())){
                throw new IllegalArgumentException("组件地址不合法");
            }
        } else if(entity.getType() == ResourceType.BUTTON) {
            // 按钮 必须从属于某个菜单
            if(entity.getParentId() == null) {
                throw new IllegalArgumentException("归属菜单不合法");
            }
        } else {
            throw new IllegalArgumentException("暂不支持的资源类型");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<Long> resourceIds) {
        // 删除 角色资源关系、删除自身&所有子级关系
        // 获取资源下所有子级资源, 再加上本身资源节点 批量删除
        List<SysResource> all = resourceDao.findAll(new HashMap<>());
        List<SysResource> list = new ArrayList<>();
        for(Long resourceId : resourceIds) {
            sortSysResourceList(resourceId, all, list);
        }
        list.stream().forEach(r -> resourceIds.add(r.getId()));
        userResourceDao.batchDeleteByResourceIds(resourceIds);
        roleResourceDao.batchDeleteByResourceIds(resourceIds);
        resourceDao.batchDelete(resourceIds);
        return true;
    }

    @Override
    public SysResource get(Serializable id) {
        return resourceDao.get(id);
    }

    @Override
    public List<SysResource> queryList(Map<String, Object> params) {
        List<SysResource> all = resourceDao.findAll(params);
        // List<SysResource> list = new ArrayList<>();
        // sortSysResourceList(params.get("parentId") == null ? 0L : Long.valueOf(params.get("parentId").toString()), all, list);
        return all;
    }

    private void sortSysResourceList(Long parentId, List<SysResource> all, List<SysResource> list) {
        for(SysResource resource : all) {
            if(resource.getParentId().equals(parentId)) {
                list.add(resource);
                if(all.stream().filter(r -> r.getParentId().equals(resource.getId())).findAny() != null) {
                    sortSysResourceList(resource.getId(), all, list);
                }
            }
        }
    }

    @Override
    public JSONArray queryTree(Map<String, Object> params) {
        List<SysResource> all = resourceDao.findAll(params);
        Set<Long> parentIds = new HashSet<>();
        all.stream().forEach(r -> {
            parentIds.add(r.getParentId());
        });
        JSONArray array = new JSONArray();
        transSysResourceTree(params.get("parentId") == null ? 0L : Long.valueOf(params.get("parentId").toString()), all, array, parentIds);
        return array;
    }

    private void transSysResourceTree(Long parentId, List<SysResource> all, JSONArray array, Set<Long> parentIds) {
        for(SysResource resource : all) {
            if(resource.getParentId().equals(parentId)) {
                JSONObject parent = JSON.parseObject(JSON.toJSONString(resource, SerializerFeature.WriteMapNullValue));
                array.add(parent);
                //if(all.stream().filter(r -> r.getParentId().equals(resource.getId())).findAny() != null) {
                    if(!parentIds.contains(resource.getId())) {
                        parent.put("children", null);
                        continue;
                    }
                    JSONArray children = new JSONArray();
                    parent.put("children", children);
                    transSysResourceTree(resource.getId(), all, children, parentIds);
                //}
            }
        }
    }
}
